﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using SoftwareConsulting.BI11.Controls.Properties;

namespace SoftwareConsulting.BI11.Controls
{    
    /// <summary>
    /// Групбокс с редактируемым заголовком
    /// </summary>
    public class EditableGroupBox:DevExpress.XtraEditors.GroupControl
    {
        public event EditableGroupBoxCaptionChanging OnEditableGroupBoxCaptionChanging;
        public event EditableGroupBoxCaptionBeforeEdit OnEditableGroupBoxCaptionBeforeEdit;
        public event EditableGroupBoxCaptionBeforeEdit OnEditableGroupBoxCaptionAfterEdit;
        private string _beforeCaption;
        private TextBox _captionBox;
        private ContextMenuStrip _contextMenu;

        /// <summary>
        /// Обрабатывает валидацию поля редактирования заголовка
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void captionBox_Validating(object sender, CancelEventArgs e)
        {            
            CancelEventArgs args = new CancelEventArgs(false);
            if (OnEditableGroupBoxCaptionChanging != null)
            {                
                OnEditableGroupBoxCaptionChanging(_captionBox.Text, ref args);
            }
            if (!args.Cancel)
            {
                Text = _captionBox.Text;
                _captionBox.Dispose();
                _captionBox = null;
                if (OnEditableGroupBoxCaptionAfterEdit != null)
                {
                    OnEditableGroupBoxCaptionAfterEdit();
                }
            }
            e.Cancel = args.Cancel;            
        }

        /// <summary>
        /// Обрабатывает нажатие клавиши в поле редактирования заголовка
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _captionBox_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Escape:
                    _captionBox.Validating -= captionBox_Validating;
                    _captionBox.Dispose();
                    _captionBox = null;
                    Text = _beforeCaption;
                    this.Focus();
                    if (OnEditableGroupBoxCaptionAfterEdit != null)
                    {
                        OnEditableGroupBoxCaptionAfterEdit();
                    }
                    break;   
                case Keys.Enter:
                    EndEdit();
                    break;
            }
        }

        /// <summary>
        /// Выходит из режима редактирования заголовка
        /// </summary>
        public void EndEdit()
        {
            this.Focus();
        }

        /// <summary>
        /// Входит в режим редактирования заголовка
        /// </summary>
        public void BeginEdit()
        {
            if (_captionBox != null)
                return; //уже в состоянии редактирования
            if (OnEditableGroupBoxCaptionBeforeEdit != null)
            {
                OnEditableGroupBoxCaptionBeforeEdit();
            }
            _beforeCaption = Text;
            Text = string.Empty;
            _captionBox = new TextBox();
            _captionBox.Validating += new System.ComponentModel.CancelEventHandler(captionBox_Validating);
            _captionBox.KeyDown += new KeyEventHandler(_captionBox_KeyDown);
            _captionBox.Parent = this;
            _captionBox.Top = GetCaptionVertical() + (CaptionImage != null ? CaptionImage.Height / 2 : 0);// CaptionLocation.HasFlag(DevExpress.Utils.Locations.Top) ? 2 : Height - 22;
            _captionBox.Left = GetCaptionHorizontal() + (CaptionImage != null ? CaptionImage.Width / 2 : 0);
            _captionBox.Width = Width - _captionBox.Left - (CaptionImage != null ? CaptionImage.Width / 2 : 0);
            _captionBox.MaxLength = 255;
            _captionBox.Text = _beforeCaption;
            _captionBox.Visible = true;
            _captionBox.Focus();
            _captionBox.SelectAll();
        }

        /// <summary>
        /// Обрабатывает клик по заголовку
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EditableGroupBox_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left)
                return;
            if (((CaptionLocation.HasFlag(DevExpress.Utils.Locations.Top)) && (e.Y < ((CaptionImage != null ? CaptionImage.Height : 0) + CaptionImagePadding.Vertical)))
            || ((CaptionLocation.HasFlag(DevExpress.Utils.Locations.Bottom)) && (e.Y > Height - ((CaptionImage != null ? CaptionImage.Height : 0) + CaptionImagePadding.Vertical))))
                BeginEdit();
        }

        /// <summary>
        /// Обрабатывает клик по пункту контекстного меню "изменить название"
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ContextMenu_ChangeCaption_Click(object sender, EventArgs e)
        {            
            BeginEdit();
        }

        /// <summary>
        /// Конструктор контрола
        /// </summary>
        public EditableGroupBox()
            : base()
        {
            if (!CaptionLocation.HasFlag(DevExpress.Utils.Locations.Top) && !CaptionLocation.HasFlag(DevExpress.Utils.Locations.Bottom))
                CaptionLocation = DevExpress.Utils.Locations.Top; //нельзя чтоб заголовок был слева или справа в этом контроле
            CaptionImageLocation = DevExpress.Utils.GroupElementLocation.BeforeText;//всегда так в этом контроле
            MouseClick += new System.Windows.Forms.MouseEventHandler(EditableGroupBox_MouseClick);
            _contextMenu = new ContextMenuStrip();
            _contextMenu.Items.Add(Resources.BI_EDITABLEGROUPBOX_CONTEXTMENU_CHANGECAPTION);
            _contextMenu.Items[0].Click += new EventHandler(ContextMenu_ChangeCaption_Click);
            ContextMenuStrip = _contextMenu;
        }
    }
    
    public delegate void EditableGroupBoxCaptionChanging(string newCaption, ref CancelEventArgs args);
    public delegate void EditableGroupBoxCaptionBeforeEdit();
    public delegate void EditableGroupBoxCaptionAfterEdit();
}
